package com.mrjy.wechat.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertySetStrategy;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.mrjy.common.entity.UserInfo;
import com.mrjy.common.util.GlobalConstant;
import com.mrjy.common.util.HttpUtil;
import com.mrjy.common.util.PropertyStrategyWrapper;
import com.mrjy.common.util.ResultUtil;
import com.mrjy.maintain.bo.IUserInfoBo;
import com.mrjy.maintain.util.RoleInfoEnum;
import com.mrjy.wechat.bo.IWeChatOAuthBo;
import com.mrjy.wechat.conts.WxConsts;
import com.mrjy.wechat.process.AccessToken;
import com.mrjy.wechat.util.WeChatUtil;
/**
 * weChat 网页授权控制类
 * @author csshui
 *
 */
@Controller
@RequestMapping("weChat/wxOAuth")
public class WeChatOAuthController  {
	private static Logger log = Logger.getLogger(WeChatOAuthController.class);
	 @Resource
	 private IWeChatOAuthBo weChatOAuthBo;

    @Resource
    private IUserInfoBo userInfoBo;

	/**
	 * 微信网页授权登陆
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@RequestMapping("/wxOAuthLogin")
	@ResponseBody
	public String wxLogin(HttpServletRequest request, HttpServletResponse response , @RequestParam("returnUrl")String returnUrl) throws IOException{
		log.debug("====debug=wxOAuthLogin==>");
		//跳转的路径
		String backUrl = WxConsts.PUBLIC_DOMAIN + returnUrl ;
//		String backUrl = WxConsts.PUBLIC_DOMAIN + "/mrjy/weChat/wxOAuth/redirectUri.do" ;
		
		//用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
		String scope = "snsapi_userinfo";
		//组装 获取code的url
        String url = WxConsts.getWeChatApiURL(WxConsts.GET_OAUTH_CODE_URL, WxConsts.APPID,backUrl,	scope);
		System.out.println(" --------------------------------------------------->"+url);
//		String result = HttpUtil.doGet(url);
		
		return url;
	}
	
	@RequestMapping("/redirectUri")
	@ResponseBody
	public Object redirectUri(HttpServletRequest request, HttpServletResponse response ,@RequestParam("code")String code,@RequestParam("state")String state){
		System.out.println(code);
		System.out.println(state);
		
		String wxOAuthCallBack = WxConsts.PUBLIC_DOMAIN + "/mrjy/weChat/wxOAuth/wxOAuthCallBack.do";
		Map<String, String> paraMap = new HashMap<String,String>();
		if(StringUtils.isNotBlank(code)){
			paraMap.put("code", code);
			String data = HttpUtil.doPost(wxOAuthCallBack, paraMap);
			System.out.println(data);
		}
		
		
		
		return "redirect:"+WxConsts.PUBLIC_DOMAIN+"/phoneWeb/test.html";
	}

	
	/**
	 * 微信登陆回调
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@RequestMapping("/wxOAuthCallBack")
	@ResponseBody
	public Object wxcallBack(HttpServletRequest request, HttpServletResponse response , @RequestParam("code")String code) throws IOException{
		Map<String, Object> map = new HashMap<String, Object>();
		if (StringUtils.isNotBlank(code)) {
			String tokenUrl =WxConsts.getWeChatApiURL(WxConsts.GET_OAUTH_TOKEN_URL , WxConsts.APPID, WxConsts.APPSECRET, code) ;
			/**
			 * 正确格式：
			 * { "access_token":"ACCESS_TOKEN",  
				 "expires_in":7200,   
				 "refresh_token":"REFRESH_TOKEN",   
				 "openid":"OPENID",   
				 "scope":"SCOPE" } 
				 错误格式：{"errcode":40029,"errmsg":"invalid code"} 
			 */
			JSONObject jobj = WeChatUtil.httpsRequest(tokenUrl,WxConsts.HTTP_GET, null);
			System.out.println(jobj.toString());
			if (!jobj.has("errcode")) {
				//{"errcode":40163,"errmsg":"code been used, hints: [ req_id: GS..uA0339th26 ]"}
				
				JSONObject userInfoObj  = null;
				//获取openid
				String openid = jobj.getString("openid");
				//获取access_token
				String token =  jobj.getString("access_token");
				
				String userInfoUrl = WxConsts.getWeChatApiURL(WxConsts.GET_OAUTH_USERINFO_URL, token, openid);
				userInfoObj = WeChatUtil.httpsRequest(userInfoUrl, WxConsts.HTTP_GET, null);
				
				
				System.out.println(userInfoObj.toString());
				map.put("info", userInfoObj);
			}else{
				if("40163".equals(jobj.getString("errcode"))){//code been used
					map.put("err_code", "40163");
					map.put("err_msg", "code been used");
					System.out.println("--------------------------------------------->:jobj.toString(): " + jobj.toString());
					return map;
				}
			}
			
		}
		return map;
	}


	/**
	 * 获取js_sdk签名需要的参数 
	 * @param url url 当前网页的URL，必须和调用wxjs的页面地址相同并且是进行过ICP备案验证的可信域名，不包含#及其后面部分
	 * @return 包含签名(key=signature)、随机字符串(key=noncestr)、时间戳(key=timestamp)、appid的Map对象
	 */
	@RequestMapping("/jsSdkSign")
	@ResponseBody
	public Object jsSdkSign(@RequestParam String url){
		return weChatOAuthBo.jsSdkSign(url);
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @param signature  微信加密签名
	 * @param timestamp 时间戳
	 * @param nonce 随机数
	 * @param echostr 随机字符串
	 */
	@RequestMapping("/validSign")
    public void validSign(
            HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam(value = "signature", required = true) String signature,
            @RequestParam(value = "timestamp", required = true) String timestamp,
            @RequestParam(value = "nonce", required = true) String nonce,
            @RequestParam(value = "echostr", required = true) String echostr) {
        try {
            if (WeChatUtil.checkSignature(signature, timestamp, nonce)) {
                PrintWriter out = response.getWriter();
                out.print(echostr);
                out.close();
            } 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到微信pc端登录的二维码地址
     * lyon
     * @param request
     * @param response
     */
    @RequestMapping("/weixinPCCallBack")
    @ResponseBody
    public Object weixinPCCallBack(HttpServletRequest request,
                                  HttpServletResponse response){

        String pcAppid=WxConsts.PC_APPID;
        String redirct = WxConsts.PC_PUBLIC_DOMAIN + "/mrjy/weChat/wxOAuth/validLoginForPC.do";
        try {
            redirct = URLEncoder.encode(redirct, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        String state = request.getParameter("state");

        String basic_str="https://open.weixin.qq.com/connect/qrconnect?appid="+pcAppid+"&redirect_uri="+redirct+"&response_type=code&scope=snsapi_login&state="+state+"#wechat_redirect";
        return basic_str;
    }


    /**
     * lyon pc端 扫码登录
     * @param request
     * @param response
     */
    @RequestMapping("/validLoginForPC")
    public Object validLoginForPC(HttpServletRequest request,
                                  HttpServletResponse response, HttpSession session,RedirectAttributes model){

        String pcAppid=WxConsts.PC_APPID;
        String pcAppsecret=WxConsts.PC_APPSECRET;

        String state = request.getParameter("state");
        String code=request.getParameter("code");
        String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+pcAppid+"&secret="+pcAppsecret+"&code="+code+"&grant_type=authorization_code";
        String result= HttpUtil.doGet(url);
        System.out.println(result);
        JSONObject jsonObject = JSONObject.fromObject(result);
        System.out.println(jsonObject);


        String basic_str="https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        String format_url = String.format(basic_str, jsonObject.get("access_token"), jsonObject.get("openid"));
        String user_info = HttpUtil.doGet(format_url);
        JSONObject user_info_object = JSONObject.fromObject(user_info);
        System.out.println(user_info_object);
        UserInfo userInfo = null;
        if(user_info_object.has("unionid")){
        	 String unionid = user_info_object.getString("unionid");
        	 userInfo = userInfoBo.queryByWeixinUnionid(unionid);
        }

        if (userInfo == null) {
            //注册
            JsonConfig cfg = new JsonConfig();

            cfg.setPropertySetStrategy(new PropertyStrategyWrapper(PropertySetStrategy.DEFAULT));
            cfg.setRootClass(UserInfo.class);

            UserInfo userInfo1 = (UserInfo)jsonObject.toBean(user_info_object, cfg);

            userInfo1.setUserName(user_info_object.getString("nickname"));
            userInfo1.setHeadImgUrl(user_info_object.getString("headimgurl"));
            userInfo1.setCounty(user_info_object.getString("country"));
            userInfo1.setRoleId(RoleInfoEnum.STUDENT.getRoleId());
            userInfo1.setSessionIdPC(session.getId());
            userInfo1.setPicName("avator.png");
            if (user_info_object.get("unionid")!=null){
                userInfo1.setWeixinUnionid(user_info_object.getString("unionid"));
            } else {
                return "error";
            }

            int i = userInfoBo.txAddUserInfo(userInfo1);
            userInfo1.setLogin_way(WxConsts.PC_LOGIN_CODE);
            request.getSession().setAttribute(GlobalConstant.USER_INFO,userInfo1);
        }else {
            //登录
            String weixinUnionid = userInfo.getWeixinUnionid();
            if (weixinUnionid ==null){
                userInfo.setWeixinUnionid(user_info_object.getString("unionid"));
            }
            //更新union_id
            userInfo.setSessionIdPC(session.getId());
            userInfoBo.updateById(userInfo);
            userInfo.setLogin_way(WxConsts.PC_LOGIN_CODE);
            request.getSession().setAttribute(GlobalConstant.USER_INFO,userInfo);
        }
        model.addFlashAttribute("msg", userInfo);
//      return "home";//此方式跳转，页面刷新会重复提交表单
        return "redirect:" + WxConsts.PC_PUBLIC_DOMAIN + "/pcWeb/index.html?wx_login=ok";
    }
    /**
     * 检测当前用户信息是否关注过服务号
     * @author Javin
     * @param session
     * @return
     */
    @RequestMapping("/isFocus365jzkt")
    @ResponseBody
    public Object isFocus365jzkt(HttpSession session){
    	UserInfo userInfo = (UserInfo) session.getAttribute(GlobalConstant.USER_INFO);
    	Map<String, Object> map = new HashMap<String, Object>();
    	if(null != userInfo && StringUtils.isNotBlank(userInfo.getWeixinOpenid())){
    		AccessToken accessToken = WxConsts.getAccessToken();
    		if(null == accessToken){
    			accessToken = weChatOAuthBo.getAccessToken(WxConsts.APPID, WxConsts.APPSECRET);
    		}
    		if(null != accessToken && StringUtils.isNotBlank(accessToken.getAccessToken())){
    			String getUserInfoUrl =WxConsts.getWeChatApiURL(WxConsts.GET_USER_INFO ,accessToken.getAccessToken(),userInfo.getWeixinOpenid());
    			JSONObject jobj = WeChatUtil.httpsRequest(getUserInfoUrl,WxConsts.HTTP_GET, null);
    			if(null != jobj){
    				if("1".equals(jobj.getString("subscribe"))){
    					map.put("err_code", 200);
        				map.put("err_msg", "该用户已经关注服务号");
    				}else if("0".equals(jobj.getString("subscribe"))){
    					map.put("err_code", 201);
        				map.put("err_msg", "该用户没有关注服务号");
    				}else if(jobj.has("errcode")){
    					map.put("err_code", 202);
        				map.put("err_msg", "请求返回错误信息");
    				}
    			}
    		}else{
    			map.put("err_code", -2);
    			map.put("err_msg", "accessToken不存在");
    		}
    	}else{
    		map.put("err_code", -1);
			map.put("err_msg", "当前用户信息不存在");
    	}
    	return map;
    }

    /**
     * 微信绑定回调
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/wxOAuthBinding")
    public Object wxOAuthBinding(HttpServletRequest request, HttpServletResponse response , @RequestParam("code")String code) throws IOException{
        Map<String, Object> map = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(code)) {
            String state = request.getParameter("state");
            String tokenUrl =WxConsts.getWeChatApiURL(WxConsts.GET_OAUTH_TOKEN_URL , WxConsts.APPID, WxConsts.APPSECRET, code) ;
            /**
             * 正确格式：
             * { "access_token":"ACCESS_TOKEN",
             "expires_in":7200,
             "refresh_token":"REFRESH_TOKEN",
             "openid":"OPENID",
             "scope":"SCOPE" }
             错误格式：{"errcode":40029,"errmsg":"invalid code"}
             */
            JSONObject jobj = WeChatUtil.httpsRequest(tokenUrl,WxConsts.HTTP_GET, null);
            System.out.println(jobj.toString());
            if (!jobj.has("errcode")) {
                //{"errcode":40163,"errmsg":"code been used, hints: [ req_id: GS..uA0339th26 ]"}

                JSONObject userInfoObj  = null;
                //获取openid
                String openid = jobj.getString("openid");
                String unionid = jobj.getString("unionid");

                //mobilePhone_userinfo 绝对不为空
                UserInfo mobilePhone_userinfo = (UserInfo)userInfoBo.queryByMobilePhone(state);
                UserInfo openid_userInfo = userInfoBo.queryByWeixinOpenid(openid);

                if (openid_userInfo==null){
                    //说明用户没有登录过公众号,那么就直接绑定
                    mobilePhone_userinfo.setWeixinOpenid(openid);
                    mobilePhone_userinfo.setWeixinUnionid(unionid);
                    userInfoBo.updateById(mobilePhone_userinfo);
                    request.getSession().setAttribute("binding_way","new_weixin");
                    return "forward:/weixin/weixin_bind.jsp";
                }else if(StringUtils.isNotBlank(openid_userInfo.getMobilePhone())){
                    request.getSession().setAttribute("binding_way","already_ok");
                    return "forward:/weixin/weixin_bind.jsp";
                }else{
                    //就要迁移手机号码，并且disable设置为1
                    openid_userInfo.setWeixinUnionid(unionid);
                    //迁移密码
                    openid_userInfo.setPassword(mobilePhone_userinfo.getPassword());
                    userInfoBo.updateMobilePhone(mobilePhone_userinfo.getMobilePhone(),openid_userInfo);
                    //
                    mobilePhone_userinfo.setDisableFlag(1);
                    userInfoBo.updateById(mobilePhone_userinfo);

                    request.getSession().setAttribute("binding_way","move_mobilePhone");
                    return "forward:/weixin/weixin_bind.jsp";
                }
            }else{
                request.getSession().setAttribute("binding_way","error");
                return "forward:/weixin/weixin_bind.jsp";
            }
        }
        request.getSession().setAttribute("binding_way","error");
        return "forward:/weixin/weixin_bind.jsp";
    }

    /**
     * 微信网页绑定URL
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/wxOAuthBindingUrl")
    @ResponseBody
    public String wxOAuthBindingUrl(HttpServletRequest request, HttpServletResponse response , @RequestParam("returnUrl")String returnUrl
    ,@RequestParam("state")String state) throws IOException{

        //跳转的路径
        String backUrl = WxConsts.PUBLIC_DOMAIN + returnUrl ;

        //用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
        String scope = "snsapi_userinfo";

        //组装 获取code的url
        String url = WxConsts.getWeChatApiURL(WxConsts.GET_BINDING_CODE_URL, WxConsts.APPID,backUrl,	scope,state);
        System.out.println(" --------------------------------------------------->"+url);
        return url;
    }
    
    /**
	 * 小程序授权登陆
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@RequestMapping("/miniOAuthLogin")
	@ResponseBody
	public Object miniOAuthLogin(@RequestBody Map<String , Object> para,HttpSession session) {
		return weChatOAuthBo.miniOAuthLogin(para , session) ;
		
	}
	
	/**
	 * @author Javin
	 * @date 2018年7月10日
	 * @desc 与服务端建立连接
	 * @param userId
	 * @param session
	 */
	@RequestMapping("/connectSession")
	@ResponseBody
	public Object connectSession(@RequestParam(value="userId") Integer userId, HttpSession session){
		UserInfo info = (UserInfo) session.getAttribute(GlobalConstant.USER_INFO);
		if(null != info){
			return ResultUtil.success(info);
		}
		if(null == userId){
			return ResultUtil.error();
		}
		UserInfo exist = (UserInfo) weChatOAuthBo.connectSession(userId);
		if(null != exist){
			session.setAttribute(GlobalConstant.USER_INFO, exist);
			return ResultUtil.success(exist);
		}else{
			return ResultUtil.error();
		}
		
	}

}
